package com.sec.android.app.myfiles.facade.cmd;

import android.app.Activity;
import android.app.FragmentManager;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.Toast;

import com.sec.android.app.myfiles.R;
import com.sec.android.app.myfiles.dialog.EditTextDialogFragment;
import com.sec.android.app.myfiles.facade.MyFilesFacade;
import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.info.AppConstants;
import com.sec.android.app.myfiles.info.FileType;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.log.SamsungAnalyticsLog;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.module.abstraction.FileRecord.StorageType;
import com.sec.android.app.myfiles.module.cloud.CloudFileRecord;
import com.sec.android.app.myfiles.navigation.NavigationInfo;
import com.sec.android.app.myfiles.navigation.NavigationInfo.NavigationMode;
import com.sec.android.app.myfiles.navigation.NavigationManager;
import com.sec.android.app.myfiles.operation.FileOperationArgs;
import com.sec.android.app.myfiles.operation.FileOperator;
import com.sec.android.app.myfiles.operation.ProgressListener;
import com.sec.android.app.myfiles.provider.DbTableInfo;

import org.puremvc.java.multicore.interfaces.INotification;
import org.puremvc.java.multicore.patterns.command.SimpleCommand;

import java.util.ArrayList;
import java.util.Locale;
import java.util.regex.Pattern;

public class CreateDirCmd extends SimpleCommand implements EditTextDialogFragment.EditTextCallback, ProgressListener {
    private EditTextDialogFragment mEditDialog;
    private FileOperator mFileOperator;
    private FileRecord mFileRecord;
    private FileRecord mNewDirRecord;
    AbsMyFilesFragment mFileListFragment;
    private Activity mActivity;
    private Context mContext;
    private String mFolderName;

    public void execute(INotification notification) {
        Object[] params = (Object[]) notification.getBody();

        mContext = (Context) params[0];
        mFileListFragment = (AbsMyFilesFragment) params[1];
        mFileRecord = (FileRecord) params[2];
        mFolderName = (String) params[3];

        String tag = CreateDirCmd.class.getSimpleName();

        if (!isSameDialogShowing(tag)) {
            mFileOperator = new FileOperator(mFileListFragment.getProcessId(), mContext, mFileListFragment.getFragmentManager(), null);
            mFileOperator.registerProgressListener(this, null);

            if ((mFolderName != null) && (mFolderName.length() > AppConstants.MAX_INPUT_LENGTH)) {
                mFolderName = mFolderName.substring(0, AppConstants.MAX_INPUT_LENGTH);
            }

            String defaultText = mFileRecord.getStorageType() == StorageType.Cloud ?
                    getNewCloudFolderItem((CloudFileRecord) mFileRecord) :
                    getNewFolderItem(mFileRecord.getFullPath());

            mEditDialog = new EditTextDialogFragment.Builder()
                    .setEditTextCallback(this)
                    .setTitle(R.string.menu_create_folder)
                    .setOkText(R.string.create)
                    .setDefaultText(defaultText)
                    .build();
            mEditDialog.showAllowingStateLoss(mFileListFragment.getFragmentManager(), tag);
        }
    }

    private boolean isSameDialogShowing(String tag) {
        boolean bRet = false;
        FragmentManager fm = mFileListFragment.getFragmentManager();
        if (fm != null) {
            EditTextDialogFragment dialog = (EditTextDialogFragment) fm.findFragmentByTag(tag);
            if (dialog != null && dialog.getDialog() != null && dialog.getDialog().isShowing()) {
                Log.i(this, "Already same dialog is showing");
                bRet = true;
            }
        }

        return bRet;
    }

    private String getNewFolderItem(String path) {
        int count = 1;
        String baseName = TextUtils.isEmpty(mFolderName) ? mContext.getResources().getString(R.string.new_folder) : mFolderName;
        String newFolderName = baseName;

        if (path != null) {
            DbTableInfo tableInfo = DbTableInfo.getInstance(StorageType.Local);
            String[] projection = new String[]{tableInfo.getColumnName(DbTableInfo.COLUMN_ID.NAME)};
            String where = tableInfo.getColumnName(DbTableInfo.COLUMN_ID.IS_DIRECTORY) + "=1 AND " +
                    tableInfo.getColumnName(DbTableInfo.COLUMN_ID.PATH) + "=? AND " + tableInfo.getColumnName(DbTableInfo.COLUMN_ID.NAME) + " LIKE '" + baseName + "%'";
            String[] whereArgs = new String[]{path};

            try (Cursor cursor = mContext.getContentResolver().query(Uri.parse(tableInfo.getUri()), projection, where, whereArgs, null)) {
                int scanCount = (cursor.getCount() + "").length();
                boolean isNewScanRequired = true;
                for (int i = 0; i < scanCount && isNewScanRequired; i++) {
                    isNewScanRequired = false;
                    if (cursor != null && cursor.moveToFirst()) {
                        do {
                            String strExistName = cursor.getString(0);
                            if (strExistName.trim().toLowerCase(Locale.getDefault())
                                    .equals(newFolderName.trim().toLowerCase(Locale.getDefault()))) {
                                newFolderName = baseName + " " + String.format(Locale.getDefault(), "%d", count++);
                                isNewScanRequired = true;
                            }
                        } while (cursor.moveToNext());
                    }
                }
            } catch (Exception e) {
                Log.e(this, "Exception : " + e.getMessage());
            }
        }
        return newFolderName;
    }

    private String getNewCloudFolderItem(CloudFileRecord fileRecord) {
        int count = 1;
        boolean isFolderExist;

        String baseName = mFolderName == null ? mContext.getResources().getString(R.string.new_folder) : mFolderName;
        String newFolderName = baseName;

        if (fileRecord != null) {
            do {
                isFolderExist = false;
                if (fileRecord.exists(mContext, newFolderName, fileRecord.getFileId())) {
                    isFolderExist = true;
                    newFolderName = baseName + " " + String.format(Locale.getDefault(), "%d", count++);
                }
            } while (isFolderExist);
        }

        return newFolderName;
    }

    @Override
    public boolean checkNameExist(String inputString) {
        return false;
    }

    @Override
    public boolean checkText(String inputString, Activity activity) {
        boolean bRet = true;

        Pattern ps = Pattern.compile("\\.*");

        if (!TextUtils.isEmpty(inputString)) {
            mNewDirRecord = getNewDirRecord(mFileRecord, inputString);
            if (inputString != null && ps.matcher(inputString).matches()) {
                mEditDialog.setInputErrorEnabled(true);
                mEditDialog.setInputError(activity.getString(R.string.folder_name_invalid_characters));
                bRet = false;
            } else if (mNewDirRecord != null && mNewDirRecord.exists(activity)) {
                mEditDialog.setInputErrorEnabled(true);
                mEditDialog.setInputError(activity.getString(R.string.folder_name_exist));
                bRet = false;
            }
        }
        return bRet;
    }

    @Override
    public void onOK(String inputString, Activity activity) {
        if (checkText(inputString, activity)) {
            mActivity = activity;
            FileOperationArgs args = new FileOperationArgs();
            args.mDst = mFileRecord;
            args.mCreateFolderName = inputString;

            try {
                if (FileOperator.isWorking()) {
                    Toast.makeText(mActivity, R.string.failed_to_create_folder, Toast.LENGTH_LONG).show();
                } else {
                    mFileOperator.setOperationArgs(FileOperator.Operation.CREATE_DIR, args);
                    mFileOperator.execute();
                    MyFilesFacade.execSpinnerProgress(mFileListFragment.mProcessId, mContext, SpinnerProgressCmd.OperationProgress.SHOW);
                }
                mEditDialog.dismiss();
            } catch (IllegalStateException e) {
                Log.e(this, "IllegalStateException:" + e.toString());
            }

            SamsungAnalyticsLog.sendLog(SamsungAnalyticsLog.ScreenPath.CREATE_FOLDER_POPUP, SamsungAnalyticsLog.Event.CREATE_FOLDER, null);
        }
    }

    @Override
    public void onCancel(Activity activity) {
        SamsungAnalyticsLog.sendLog(SamsungAnalyticsLog.ScreenPath.CREATE_FOLDER_POPUP, SamsungAnalyticsLog.Event.CANCEL, null);
    }

    @Override
    public void onFinished(boolean bRet, String msg, Bundle extras) {
        boolean showToast = true;
        if (mFileRecord.getStorageType() == StorageType.Cloud && extras != null) {
            ((CloudFileRecord) mNewDirRecord).setFileId(extras.getString(FileOperator.CREATE_DIR_BUNDLE));
            showToast = extras.getBoolean(FileOperator.SHOW_TOAST_ERROR_BUNDLE, true);
        } else {
            MyFilesFacade.reload(mFileListFragment.mProcessId, mContext, mFileRecord, mFileListFragment);
        }
        MyFilesFacade.execSpinnerProgress(mFileListFragment.mProcessId, mContext, SpinnerProgressCmd.OperationProgress.DISMISS);

        NavigationInfo curInfo = mFileListFragment.getNavigationInfo();
        if (curInfo != null) {
            if (isNeedToEnterAfterCreateFolder(bRet, curInfo.getNavigationMode())) {
                NavigationInfo info = NavigationInfo.getInstance(curInfo, mNewDirRecord);
                NavigationManager navigationMgr = NavigationManager.getInstance(mFileListFragment.getProcessId());
                navigationMgr.enter(info);
            } else {
                curInfo.setFocusRecord(mNewDirRecord);
            }
        }

        if (!TextUtils.isEmpty(msg)) {
            if (!showToast && null != mActivity) {
                MyFilesFacade.showNotEnoughStorage(mFileListFragment.mProcessId, mContext, mFileListFragment.getFragmentManager(), null, msg, FileOperator.Operation.CREATE_DIR);
            } else {
                Toast.makeText(mContext, msg, bRet ? Toast.LENGTH_SHORT : Toast.LENGTH_LONG).show();
            }
        }
    }

    @Override
    public void onProgressChanged(String fileName, int progress, int total) {
        // DON'T need IMPLEMENT
    }

    public static FileRecord getNewDirRecord(FileRecord fileRecord, String inputString) {
        String renamePath = fileRecord.getFullPath() + "/" + inputString;
        FileRecord ret = FileRecord.createFileRecord(fileRecord.getStorageType(), renamePath);

        if ((ret != null) && (fileRecord.getStorageType() == StorageType.Cloud)) {
            ((CloudFileRecord) ret).setDeviceId(((CloudFileRecord) fileRecord).getDeviceId());

            ArrayList<String> parentIds = new ArrayList<>();
            parentIds.addAll(((CloudFileRecord) fileRecord).getParentIds());
            parentIds.add(((CloudFileRecord) fileRecord).getFileId());

            ((CloudFileRecord) ret).setParentIds(parentIds);

            ret.setFileType(FileType.FOLDER);
        }
        return ret;
    }

    private boolean isNeedToEnterAfterCreateFolder(boolean result, NavigationMode naviMode) {
        boolean bRet = false;
        if (result &&
                (naviMode == NavigationInfo.NavigationMode.Select_move_destination
                        || naviMode == NavigationInfo.NavigationMode.Select_copy_destination
                        || naviMode == NavigationInfo.NavigationMode.Select_remove_from_private
                        || naviMode == NavigationInfo.NavigationMode.Select_optimize_storage_backup_destination)) {
            bRet = true;
        }
        return bRet;
    }
}
